﻿#region

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using CuongHanh.Context;
using CuongHanh.DAL;
using CuongHanh.Models;
using CuongHanh.Models.View;
using Ext.Net.Utilities;

#endregion

namespace CuongHanh.Service
{
    public class MyStyleService : BaseService
    {
        public static string Gets(int start,
                int limit,
                string q)
        {
            var query = MultiCache<MyStyle>.Singleton.GetObjectsByFilter(c => (c.Code.Contains(q) || c.Name.Contains(q)) && !c.Inactive)
                    .Select(c => new
                                 {
                                         c.Id,
                                         c.Name,
                                         c.NameEn,
                                         c.Code,
                                         c.ParentId,
                                         c.Image,
                                         c.StyleTypeId,
                                         c.LastModified
                                 });
            return FormatResult(query.Count(),
                    query.OrderByDescending(c => c.LastModified).Skip(start).Take(limit));
        }

        public static MyStyle Get(int id)
        {
            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                return unitOfWork.GetById<MyStyle>(id);
            }
        }

        public static UpdateResult Insert(MyStyle model)
        {
            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                unitOfWork.Insert(model);
                unitOfWork.Save();
                MultiCache<MyStyle>.Singleton.UpdateCached(model);
                return new UpdateResult(1,
                        string.Format("Insert MyStyle {0} successful!",
                                model.Name));
            }
        }

        public static UpdateResult Update(MyStyle newModel)
        {
            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                MyStyle model = unitOfWork.GetById<MyStyle>(newModel.Id);
                if(model != null)
                {
                    model.UpdateInfo(newModel);
                    unitOfWork.Save();
                    MultiCache<MyStyle>.Singleton.UpdateCached(model);
                    return new UpdateResult(1,
                            string.Format("Update MyStyle Id = {0} successful!",
                                    newModel.Id));
                }
                return new UpdateResult(4,
                        string.Format("Update MyStyle Id = {0} error!",
                                newModel.Id));
            }
        }

        public static UpdateResult UpdateDescription(MyStyle newModel)
        {
            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                MyStyle model = unitOfWork.GetById<MyStyle>(newModel.Id);
                if (model != null)
                {
                    model.Description = newModel.Description;
                    model.DescriptionEn = newModel.DescriptionEn;
                    unitOfWork.Save();
                    MultiCache<MyStyle>.Singleton.UpdateCached(model);
                    return new UpdateResult(1,
                            string.Format("Update MyStyle Id = {0} successful!",
                                    newModel.Id));
                }
                return new UpdateResult(4,
                        string.Format("Update MyStyle Id = {0} error!",
                                newModel.Id));
            }
        }

        public static UpdateResult Delete(int id)
        {
            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                MyStyle oldModel = unitOfWork.GetById<MyStyle>(id);
                if(oldModel != null)
                {
                    oldModel.Inactive = true;
                    oldModel.LastModified = DateTime.Now;
                    unitOfWork.Save();
                    MultiCache<MyStyle>.Singleton.UpdateCached(oldModel);
                    return new UpdateResult(1,
                            string.Format("Delete MyStyle Id = {0} successful!",
                                    id));
                }
                return new UpdateResult(4,
                        string.Format("Delete MyStyle Id = {0} error!",
                                id));
            }
        }

        public static string GetStylesCombo()
        {
            var query = MultiCache<MyStyle>.Singleton.GetObjectsByFilter(c => !c.Inactive)
                    .Select(c => new
                                 {
                                         c.Id,
                                         Name = "(" + c.Code + ")" + c.Name
                                 }).OrderBy(c => c.Name).ToList();

            return FormatResult(query.Count,
                    query);
        }

        #region StyleMaterial

        public static string GetStyleMaterials(int styleId)
        {
            IEnumerable<StyleMaterial> styleMaterials = CacheList<StyleMaterial>.Singleton.GetCache(styleId);
            IEnumerable<Material> materials = CacheContext<Material>.Singleton.GetObjectsByFilter();
            var query = styleMaterials.Join(materials,
                    c => c.MaterialId,
                    v => v.Id,
                    (c,
                            v) => new
                                  {
                                          c.StyleId,
                                          c.MaterialId,
                                          MaterialName = v.Name,
                                          c.Image,
                                          c.Price,
                                          c.No
                                  });
            return FormatResult(query.Count(),
                    query.OrderBy(c=>c.No));
        }

        public static StyleMaterial GetStyleMaterial(int styleId,
                int materialId)
        {
            return CacheList<StyleMaterial>.Singleton.GetCache(styleId,
                    materialId);
        }

        public static UpdateResult DeleteMaterial(int styleId,
                int? materialId)
        {
            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                StyleMaterial oldModel = unitOfWork.FirstOrDefault<StyleMaterial>(c => c.StyleId == styleId && c.MaterialId == materialId);
                if(oldModel != null)
                {
                    unitOfWork.Delete(oldModel);
                    unitOfWork.Save();
                    CacheList<StyleMaterial>.Singleton.DeleteCache(oldModel);
                    return new UpdateResult(1,
                            string.Format("Delete Material Id = {0} successful!",
                                    materialId));
                }
                return new UpdateResult(4,
                        string.Format("Delete Material Id = {0} error!",
                                materialId));
            }
        }

        public static UpdateResult InsertStyleMaterial(StyleMaterial model)
        {
            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                unitOfWork.Insert(model);
                unitOfWork.Save();
                CacheList<StyleMaterial>.Singleton.UpdateCache(model);
                return new UpdateResult(1,
                        string.Format("Insert StyleMaterial {0}-{1} successful!",
                                model.StyleId,
                                model.MaterialId));
            }
        }

        public static UpdateResult UpdateStyleMaterial(StyleMaterial newModel)
        {
            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                StyleMaterial model = unitOfWork.FirstOrDefault<StyleMaterial>(c => c.StyleId == newModel.StyleId && c.MaterialId == newModel.MaterialId);
                if(model != null)
                {
                    model.UpdateInfo(newModel);
                    unitOfWork.Save();
                    CacheList<StyleMaterial>.Singleton.UpdateCache(model);
                    return new UpdateResult(1,
                            string.Format("Update MyStyleMaterial = {0}-{1} successful!",
                                    newModel.StyleId,
                                    newModel.MaterialId));
                }
                return new UpdateResult(4,
                        string.Format("Update MyStyleMaterial = {0}-{1} error!",
                                newModel.StyleId,
                                newModel.MaterialId));
            }
        }

        public static string GetMaterialsOfParentCombo(int styleId,
                int parentStyleId,
                int? parentMaterialId)
        {
            List<int> parentMaterialIds = Cache3Key<ParentMaterial>.Singleton.GetCache(styleId).Where(c => c.ParentStyleId == parentStyleId).Select(c => c.ParentMaterialId).ToList();
            if(parentMaterialId.HasValue)
                parentMaterialIds.Remove(parentMaterialId.Value);
            IEnumerable<StyleMaterial> models = CacheList<StyleMaterial>.Singleton.GetCache(parentStyleId).Where(c => !parentMaterialIds.Contains(c.MaterialId));
            List<MaterialView> datas = new List<MaterialView>();
            foreach (StyleMaterial styleMaterial in models)
            {
                Material temp = CacheContext<Material>.Singleton.GetObject(styleMaterial.MaterialId);
                if(temp != null)
                    datas.Add(new MaterialView()
                              {
                                      Id = temp.Id,
                                      Name = temp.Name
                              });
            }

            datas = datas.OrderBy(c => c.Name).ToList();
            return FormatResult(datas.Count,
                    datas);
        }

        #endregion

        #region StyleStone

        public static string GetStyleStones(int styleId)
        {
            IEnumerable<StyleStone> styleStones = CacheList<StyleStone>.Singleton.GetCache(styleId);
            IEnumerable<MyStone> stones = CacheContext<MyStone>.Singleton.GetObjectsByFilter();
            var query = styleStones.Join(stones,
                    c => c.StoneId,
                    v => v.Id,
                    (c,
                            v) => new
                                  {
                                          c.StyleId,
                                          c.StoneId,
                                          StoneName = v.Name,
                                          c.Image,
                                          c.Price,
                                          c.No
                                  });
            return FormatResult(query.Count(),
                    query.OrderBy(c=>c.No));
        }

        public static StyleStone GetStyleStone(int styleId,
                int stoneId)
        {
            return CacheList<StyleStone>.Singleton.GetCache(styleId,
                    stoneId);
        }

        public static UpdateResult DeleteStyleStone(int styleId,
                int? stoneId)
        {
            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                StyleStone oldModel = unitOfWork.FirstOrDefault<StyleStone>(c => c.StyleId == styleId && c.StoneId == stoneId);
                if(oldModel != null)
                {
                    unitOfWork.Delete(oldModel);
                    unitOfWork.Save();
                    CacheList<StyleStone>.Singleton.DeleteCache(oldModel);
                    return new UpdateResult(1,
                            string.Format("Delete Stone Id = {0} successful!",
                                    stoneId));
                }
                return new UpdateResult(4,
                        string.Format("Delete Stone Id = {0} error!",
                                stoneId));
            }
        }

        public static UpdateResult InsertStyleStone(StyleStone model)
        {
            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                unitOfWork.Insert(model);
                unitOfWork.Save();
                CacheList<StyleStone>.Singleton.UpdateCache(model);
                return new UpdateResult(1,
                        string.Format("Insert StyleStone {0}-{1} successful!",
                                model.StyleId,
                                model.StoneId));
            }
        }

        public static UpdateResult UpdateStyleStone(StyleStone newModel)
        {
            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                StyleStone model = unitOfWork.FirstOrDefault<StyleStone>(c => c.StyleId == newModel.StyleId && c.StoneId == newModel.StoneId);
                if(model != null)
                {
                    model.UpdateInfo(newModel);
                    unitOfWork.Save();
                    CacheList<StyleStone>.Singleton.UpdateCache(model);
                    return new UpdateResult(1,
                            string.Format("Update MyStyleStone = {0}-{1} successful!",
                                    newModel.StyleId,
                                    newModel.StoneId));
                }
                return new UpdateResult(4,
                        string.Format("Update MyStyleStone = {0}-{1} error!",
                                newModel.StyleId,
                                newModel.StoneId));
            }
        }

        #endregion

        #region ParentMaterial

        public static string GetParentMaterials(int styleId)
        {
            IEnumerable<ParentMaterial> parentMaterials = Cache3Key<ParentMaterial>.Singleton.GetCache(styleId);
            IEnumerable<MyStyle> parentStyles = MultiCache<MyStyle>.Singleton.GetObjectsByFilter();
            IEnumerable<Material> materials = CacheContext<Material>.Singleton.GetObjectsByFilter();
            var query = parentMaterials.Join(parentStyles,
                    c => c.ParentStyleId,
                    v => v.Id,
                    (c,
                            v) => new
                                  {
                                          c,
                                          v
                                  })
                    .Join(materials,
                            c => c.c.ParentMaterialId,
                            v => v.Id,
                            (c,
                                    v) => new
                                          {
                                                  c.c.ParentStyleId,
                                                  ParentStyleName = c.v.Name,
                                                  c.c.ParentMaterialId,
                                                  ParentMaterialName = v.Name,
                                                  c.c.ChildStyleId,
                                                  c.c.Price,
                                                  c.c.Image
                                          });

            return FormatResult(query.Count(),
                    query);
        }

        public static ParentMaterial GetParentMaterial(int parentStyleId,
                int parentMaterialId,
                int childStyleId)
        {
            return Cache3Key<ParentMaterial>.Singleton.GetCache(childStyleId,
                    parentStyleId,
                    parentMaterialId);
        }

        public static UpdateResult DeleteParentMaterial(int parentStyleId,
                int parentMaterialId,
                int childStyleId)
        {
            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                ParentMaterial oldModel = unitOfWork.FirstOrDefault<ParentMaterial>(c => c.ParentStyleId == parentStyleId && c.ParentMaterialId == parentMaterialId && c.ChildStyleId == childStyleId);
                if(oldModel != null)
                {
                    unitOfWork.Delete(oldModel);
                    unitOfWork.Save();
                    Cache3Key<ParentMaterial>.Singleton.DeleteCache(oldModel);
                    return new UpdateResult(1,
                            string.Format("Delete Parent Material Id = {0} successful!",
                                    parentMaterialId));
                }
                return new UpdateResult(4,
                        string.Format("Delete Parent Material Id = {0} error!",
                                parentMaterialId));
            }
        }

        public static UpdateResult InsertParentMaterial(ParentMaterial model)
        {
            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                unitOfWork.Insert(model);
                unitOfWork.Save();
                Cache3Key<ParentMaterial>.Singleton.UpdateCache(model);
                return new UpdateResult(1,
                        string.Format("Insert ParentMaterial {0}-{1}-{2} successful!",
                                model.ChildStyleId,
                                model.ParentStyleId,
                                model.ParentMaterialId));
            }
        }

        public static UpdateResult UpdateParentMaterial(ParentMaterial newModel)
        {
            using (UnitOfWork unitOfWork = new UnitOfWork())
            {
                ParentMaterial model = unitOfWork.FirstOrDefault<ParentMaterial>(c => c.ChildStyleId == newModel.ChildStyleId && c.ParentStyleId == newModel.ParentStyleId && c.ParentMaterialId == newModel.ParentMaterialId);
                if(model != null)
                {
                    model.UpdateInfo(newModel);
                    unitOfWork.Save();
                    Cache3Key<ParentMaterial>.Singleton.UpdateCache(model);
                    return new UpdateResult(1,
                            string.Format("Update MyParentMaterial = {0}-{1}-{2} successful!",
                                    newModel.ChildStyleId,
                                    newModel.ParentStyleId,
                                    model.ParentMaterialId));
                }
                return new UpdateResult(4,
                        string.Format("Update MyParentMaterial = {0}-{1}-{2} error!",
                                newModel.ChildStyleId,
                                newModel.ParentStyleId,
                                model.ParentMaterialId));
            }
        }

        #endregion

        #region ThanhToan

        public static void UpdateModelOrderDetailForGem(ref OrderDetailForGem model)
        {
            var parentStone = CacheList<StyleStone>.Singleton.GetCache(model.ParentStyleId,
                    model.ParentStoneId);
            if (parentStone != null)
                model.ParentPriceOfStone = (long)parentStone.Price;
            var parentMaterial = CacheList<StyleMaterial>.Singleton.GetCache(model.ParentStyleId,
                    model.ParentMaterialId);
            if (parentMaterial != null)
                model.ParentPriceOfMaterial = (long)parentMaterial.Price;

            var childStone = CacheList<StyleStone>.Singleton.GetCache(model.ChildStyleId,
                   model.ChildStoneId);
            if (childStone != null)
                model.ChildPriceOfStone = (long)childStone.Price;
            var childMaterial = CacheList<StyleMaterial>.Singleton.GetCache(model.ParentStyleId,
                    model.ChildMaterialId);
            if (childMaterial != null)
                model.ChildPriceOfMaterial = (long)childMaterial.Price;
        }
        #endregion
        public static string GetStyleTypesCombo()
        {

            var query = CacheContext<StyleType>.Singleton.GetObjectsByFilter()
                    .Select(c => new
                                 {
                                         c.Id,
                                         Name = c.NameVi
                                 }).OrderBy(c => c.Name).ToList();

            return FormatResult(query.Count,
                    query);
        }
    }
}
